package com.artfii.fluentsql.core.tools;

import com.artfii.fluentsql.core.exception.FluentSqlException;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Func:   : 对象构造工具类，私有构造方法的类也能创建
 *
 * @author : Lqf(leeton)
 * @date : 2021/7/2.
 */
@SuppressWarnings({"rawtypes","unchecked","deprecation"})
public class ObjFactory {
    private static boolean useUnsafe = true;
    private static Object theUnsafe;
    private static Method allocateInstanceMethod; // 添加静态Method属性
    
    static {
        try {
            Class unsafeClass = Class.forName("sun.misc.Unsafe");
            Field declaredField = unsafeClass.getDeclaredField("theUnsafe");
            declaredField.setAccessible(true);
            theUnsafe = declaredField.get(null);
            // 初始化Method对象并缓存
            allocateInstanceMethod = unsafeClass.getMethod("allocateInstance", Class.class);
            allocateInstanceMethod.setAccessible(true);
        } catch (Throwable e) {
            // 在JDK 9及以上版本中，尝试使用反射创建对象
            useUnsafe = false;
            theUnsafe = null;
            allocateInstanceMethod = null;
        }
    }

    public static ObjConstructor getConstructor(final Class<?> clazz) {
        return new ObjConstructor() {
            public Object instance() {
                try {
                    // 尝试使用Unsafe创建实例
                    if (useUnsafe && theUnsafe != null && allocateInstanceMethod != null) {
                        // 直接使用缓存的Method对象
                        return allocateInstanceMethod.invoke(theUnsafe, clazz);
                    } else {
                        // 如果Unsafe不可用，使用反射创建实例
                        return createInstanceViaReflection(clazz);
                    }
                } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                    throw new FluentSqlException("Could not create a new instance of class " + clazz, e);
                }
            }
        };
    }

    private static Object createInstanceViaReflection(Class<?> clazz) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        // 获取类的无参构造函数并创建实例
        return clazz.getDeclaredConstructor().newInstance();
    }

    public static <T> T instanceOf(final Class<T> clazz){
        return getConstructor(clazz).instance();
    }

    public interface ObjConstructor {
        <T> T instance();
    }


}